Repository navigation
Conversation
ASCS-eV/PufferDrive is consumed as a git submodule internally while feeding
features back to Emerge-Lab/PufferDrive. This commit carries everything that
exists only in the fork, and is the single place fork-only content lives.
Branch model:
3.0 verbatim, fast-forward-only mirror of upstream/3.0
integration/3.0 default branch; this commit plus a linear stack of
single-commit features; what internal consumers pin
feature/<slug> one feature, exactly one commit
mirror/<slug> cherry-picked onto pure upstream/3.0 for upstream PRs
integration/3.0 is the default branch because GitHub reads the PR template,
the contributing guidelines, the agent instructions and scheduled workflows
only from the default branch, and none of those files may exist on 3.0
without destroying the mirror. A clone checks out the default branch, so the
copy of the instructions here is the process as far as every agent and every
submodule consumer is concerned; a rule that lives only in an open PR has no
effect.
Nothing reaches integration/3.0 until three gates pass:
1. CI green on the final commit.
2. Adversarial review by someone other than the author, with the findings
written down -- including the probes that found nothing.
3. Upstream-readiness proven rather than asserted: the commit cherry-picks
onto a branch cut from pure upstream/3.0 and produces an upstream-clean
diff. We stack only commits we could contribute today.
chore(fork): commits are exempt from gate 3, since fork-only infrastructure
can never be upstream-ready. They carry two orthogonal markers: do-not-mirror
(must never reach upstream) and do-not-merge (the merge button is never
pressed -- merging would create a second chore(fork): commit and break the
single-commit invariant that every sync asserts). Such a PR is folded into
this commit by fixup and closed unmerged.
Contents:
- .github/copilot-instructions.md: normative process for coding agents
- CONTRIBUTING.md: human orientation, same rules
- .github/pull_request_template.md: testing and stack-hygiene gates
- .github/workflows/sync-mirror.yml: fast-forward-only mirror sync that
refuses any non-fast-forward instead of rewriting the upstream base
- AGENTS.md / CLAUDE.md: fenced pointer so agents find the fork process
without colliding with upstream-owned content
- ci.yml / install.yml: run CI for PRs targeting integration/3.0, which
upstream's branch filters would otherwise skip
A standing draft PR from integration/3.0 into 3.0 gives a continuous CI
verdict on the combined stack; it must never be merged.
Everything here is fork-only and must never be cherry-picked upstream.
The Linux CI jobs fail while installing the package:
[Errno 122] Disk quota exceeded
Errno 122 is EDQUOT, hit while unpacking the CUDA torch stack that
`pip install -e .` resolves by default. torch alone is 554.6 MB and the
accompanying nvidia-* wheels add another ~2.4 GB, which no longer fits
the runner's quota. The failure occurs during "Installing build
dependencies", i.e. the isolated PEP 517 build environment is already
enough to exceed it on its own.
The trigger is a runner image change, not a code change:
* upstream 11_bernhard_dev, 2026-10-20, Image: ubuntu-24.04 -> success
* same workflows, 2026-10-23, Image: ubuntu-26.04 -> failure
Both resolve an identical wheel set (torch 2.14.1, 554.6 MB). The
`ubuntu-latest` label began migrating to Ubuntu 26 on 2026-10-19
(actions/runner-images#14748), between those two runs. Both workflows
already carry "Free up disk space" steps, so these jobs were running
close to the limit before the migration.
Fix: install CPU-only torch from download.pytorch.org, then build with
--no-build-isolation so the build reuses it instead of resolving torch
a second time. --no-build-isolation needs the build dependencies present
up front, hence the explicit setuptools/wheel/numpy install; the
`setuptools<81` bound matches the pin already in install_requires.
This loses no coverage: BUILD_CUDA_EXT keys off CUDA_HOME/ROCM_HOME,
which is unset on these runners, so the CUDA sources were never compiled
here. tests/smoke_tests/Dockerfile already installs torch this way.
macOS keeps the plain `pip install -e .` unchanged: its PyPI wheels are
already CPU-only, and leaving it alone keeps the default PEP 517
build-isolation path under test somewhere in the matrix.
991016b to
30b1bd3
Compare
|
Gate 1 note — the two red checks are not this PR's.
It is fixed by #13, which is now 12/12 green. Once #13 is stacked and this branch is rebased, Gate 1 can be satisfied here. |
911dd26 to
c2b2121
Compare
4257145 to
a8ad898
Compare
Two scheduled jobs had been red on every run for a fortnight, and both alarms were false. `sync-mirror.yml` masked a `gh label create` failure with `|| true` and then hard-failed on the `gh issue create` that depended on the label. `fork-only-view.yml` failed its first stack invariant because the stack was one rebase behind upstream, returned early, and so silently stopped running the view-drift and standing-PR checks it exists for. Both are fixed at the root. The tracking issue is now matched by exact title, so no second object has to exist first, and it is the only alarm for an outstanding rebase. `verify_stack` gains `behind_is_notice`: a behind stack is reported as a warning and the remaining invariants are measured against the mirror the stack was built on, so a sync state can no longer disable a different detector. The rest reduces what every agent session costs. The always-loaded instructions drop from 6056 to 3941 words, with the rationale moved into PROCESS.md where it is read on demand. Review is now tiered: `forkctl track` classifies a diff as A (pufferlib, config, pufferl.py, models.py, setup.py, smoke goldens) or B (everything else), and only Track A owes a fresh-context adversarial review and the simulator suites. Nits are stated as a process bug, not a review comment. The PR template drops from 85 lines and 20 checkboxes to 56 and 7, by deleting everything forkctl check-commit already proves.
a8ad898 to
df86388
Compare
d91b4b2 to
cef3a07
Compare
|
Folded into the fork base and closed unmerged, per section 3.3.
The stack was rebased onto Verification before the push:
Note for anyone reproducing this: 13 unit tests failed on the first local run with |
What
Makes the fork process cost what the change risks, and reduces the manual steps in it to exactly
one: pressing "Rebase and merge".
The gates stop being rituals and become a check. New fork-only workflow
.github/workflows/fork-gates.ymlrunsforkctl check-commitplus the upstream-readiness proof(
forkctl mirror <slug> --sha HEAD --no-publish) on every PR intointegration/3.0, deriving theslug from the branch and the
chore(fork):exemption from the commit subject. Nobody runs thosecommands, and nobody pastes their output into a PR description any more.
Review stops being a separate blocking step. It was: an adversarial review by a non-author, run
as a fresh-context agent for Track A, posted as a PR review listing every probe including the ones
that found nothing, with each finding resolved in-thread before merge. It is now the merge decision
itself —
forkctl trackstill says how hard to read the diff,PROCESS.mdstill holds the Track Aprompts, but there is no approval to collect, nothing to post, and nothing written down unless
something was actually found.
Three gates become two checks plus the button. Gate 1 is CI. Gate 2 is
Fork gates. The oldGate 2 (review) is gone as a gate; the old Gate 3 is renumbered.
Three over-strict guards relaxed, all the same bug — conflating "this branch is correct" with
"this branch is current". Each one forced every open PR to rebase and re-run its gates whenever
anything else landed:
check-commit: "not rebased directly onto the base" was a failure, now a notice. "Rebase andmerge" already replays the commit and refuses when it cannot.
resolve_feature_commit: required the commit be parented on the tip ofintegration/3.0, nowonly that its parent is an ancestor of the stack.
fork_state_problems: reported a required fork-only file as deleted when the branch simplypredates it. Now excused only when the file is absent from the branch's own merge base — deleting
one you did inherit is still caught.
Smaller surface. PR template 54 -> 31 lines, with both gate code blocks and the three gate
checkboxes removed. Section 4.3 inverted: CI runs the suites, you owe
pre-commitplusmake rebuildfor C changes. Section 8 reduced to five bullets and no commands.CONTRIBUTING.mdand
PROCESS.mdfollow.New
forkctl mirror --no-publishproves the gate without movingmirror/<slug>, so CI cannot leavemirror branches behind.
forkctl delete-mirroris fixed to match: it treated an absent remote branchas a failed push, so a local-only mirror — now the normal case — could not be cleaned up at all.
Why
Two separate pieces of feedback. The cron jobs had been failing since 29.10 on false alarms, and the
per-PR cost had grown to: 2 gate commands run by hand, 2 pasted output blocks, 4 local suites, 7
checkboxes, a review ceremony with a written probe list, and a forced rebase every time anything
else merged. Most of that is mechanical and was already implemented in
forkctl— it was simplybeing executed by a person (or, expensively, by an agent) instead of by CI.
The parts that actually need judgement — is this the right change, and can it break the sim — do not
get cheaper by being written down twice. They get cheaper by happening once, at the moment someone
decides to merge.
Notes
The workflow was run (section 4.8 requires this of any PR that adds one):
chore(fork):and skipping the upstreamhalf.
(
if: always()), slug and chore detection correct, each failure carrying its fix. The probe istwo commits by construction — it sits on top of this unmerged chore commit — so it is a red
feature path by design.
workflow only exists on branches carrying it. Proven locally instead, with this commit's
forkctlagainst the real single-commit branch of ci: skip the test jobs on documentation-only pull requests #15:mirror ci-skip-doc-only --sha HEAD --no-publish->OK, clean cherry-pick onto pureupstream/3.0, mirror diff one file, branch not moved.Two bugs the probe found that a review would not have:
actions/checkoutwithref: <sha>leavesHEAD detached and
mirrorrefuses to run there (fixed withgit switch -c gate-head), and theparent-on-tip rule above.
Tested: full
forkctlsuite,pre-commit run --all-files,forkctl check-commit --chore.Cleanup done alongside this PR (stale state, not part of the diff): deleted the folded
chore/forkctlbranch on origin, four orphaned localmirror/*branches with no upstream PR, andtwo pre-rebase local leftovers. Every remaining branch now maps to an open PR or is structural.
This is a
chore(fork):PR. It is folded into the base commit by fixup and closed unmerged(section 3.3) — never merged with the button.
Post-fold step, do not skip: add
Fork gatesto the required checks onintegration/3.0. It isdeliberately not required yet — the workflow does not exist until this commit is in the base, and
a required check that cannot run sits pending forever and blocks every merge.
Suggested order (one history rewrite, one rebase per PR):
origin/3.0in the same step (closes issue Rebase integration/3.0 onto upstream 3.0 #19).Fork gatesto the required checks.